﻿using Microsoft.Xna.Framework;


namespace KineBall.GameLogic
{
    public class CollisionManager
    {
        GameState state;

        ContainmentType currentContainmentLeft;
        ContainmentType oldContainmentLeft;

        ContainmentType currentContainmentRight;
        ContainmentType oldContainmentRight;

        ContainmentType currentContainmentDown;
        ContainmentType oldContainmentDown;

        ContainmentType currentContainmentUp;
        ContainmentType oldContainmentUp;

        ContainmentType currentContainmentBackward;
        ContainmentType oldContainmentBackward;

        ContainmentType currentContainmentForward;
        ContainmentType oldContainmentForward;

        ContainmentType currentShieldRightContainment;
        ContainmentType oldShieldRightContainment;

        ContainmentType currentShieldLeftContainment;
        ContainmentType oldShieldLeftContainment;

        ContainmentType currentShieldOneContainment;
        ContainmentType oldShieldOneContainment;

        public CollisionManager(GameState state)
        {
            this.state = state;
            Reset();
        }

        public void Reset()
        {
            oldContainmentLeft          = ContainmentType.Disjoint;
            oldContainmentRight         = ContainmentType.Disjoint;
            oldContainmentDown          = ContainmentType.Disjoint;
            oldContainmentUp            = ContainmentType.Disjoint;
            oldContainmentBackward      = ContainmentType.Disjoint;
            oldContainmentForward       = ContainmentType.Disjoint;

            oldShieldRightContainment   = ContainmentType.Intersects;
            oldShieldLeftContainment    = ContainmentType.Intersects;
            oldShieldOneContainment     = ContainmentType.Intersects;
        }

        public GameFlow UpdateAndCheckPoint(BoundingSphere s)
        {
            bool newMatch = false;
            GameFlow matchState = GameFlow.PlayingMatch;

            // Aggiorno la BoundingSphere della palla
            s.Center += state.ball.Position + new Vector3(-0.8648543f, -1.012608f, 0.1980919f);
            s.Radius = 0.3f;

            // Collisione a sinistra/destra
            currentContainmentLeft = state.gameField.BoundingBoxLeft.Contains(s);
            currentContainmentRight = state.gameField.BoundingBoxRight.Contains(s);
            if ((currentContainmentLeft == ContainmentType.Intersects && oldContainmentLeft == ContainmentType.Disjoint) ||
                (currentContainmentRight == ContainmentType.Intersects && oldContainmentRight == ContainmentType.Disjoint))
            {
                state.ball.Direction.X *= -1.0f;
                SoundManager.PlaySound("Bounce");
            }
            oldContainmentLeft = currentContainmentLeft;
            oldContainmentRight = currentContainmentRight;

            // Collisione sotto/sopra
            currentContainmentDown = state.gameField.BoundingBoxDown.Contains(s);
            currentContainmentUp = state.gameField.BoundingBoxUp.Contains(s);
            if ((currentContainmentDown == ContainmentType.Intersects && oldContainmentDown == ContainmentType.Disjoint) ||
                (currentContainmentUp == ContainmentType.Intersects && oldContainmentUp == ContainmentType.Disjoint))
            {
                state.ball.Direction.Y *= -1.0f;
                SoundManager.PlaySound("Bounce");
            }
            oldContainmentDown = currentContainmentDown;
            oldContainmentUp = currentContainmentUp;

            // Collisione retro
            currentContainmentBackward = state.gameField.BoundingBoxBackward.Contains(s);
            if (currentContainmentBackward == ContainmentType.Intersects && oldContainmentBackward == ContainmentType.Disjoint)
            {
                matchState = GameFlow.RedPoint;
                newMatch = true;
                SoundManager.PlaySound("BallLost");
            }
            oldContainmentBackward = currentContainmentBackward;

            // Collisione fronte
            currentContainmentForward = state.gameField.BoundingBoxForward.Contains(s);
            if (currentContainmentForward == ContainmentType.Intersects && oldContainmentForward == ContainmentType.Disjoint)
            {
                matchState = GameFlow.BluePoint;
                newMatch = true;
                SoundManager.PlaySound("BallLost");
            }
            oldContainmentForward = currentContainmentForward;

            if (state.ball.Direction != Vector3.Zero)
                state.ball.Direction.Normalize();

            // Gestione della collisione con lo scudo right del player
            currentShieldRightContainment = state.redShieldRight.BoundingBox.Contains(s);
            currentShieldLeftContainment = state.redShieldLeft.BoundingBox.Contains(s);

            if ((currentShieldRightContainment == ContainmentType.Intersects) && (oldShieldRightContainment == ContainmentType.Disjoint))
            {
                state.ball.Direction.Z *= -1.0f;

                if (state.ball.Position.X <= state.redShieldRight.position.X - 0.25f)
                {
                    state.ball.Direction.X -= 0.5f;
                }
                else if (state.ball.Position.X >= state.redShieldRight.position.X + 0.25f)
                {
                    state.ball.Direction.X += 0.5f;
                }
                if (state.ball.Position.Y <= state.redShieldRight.position.Y - 0.25f)
                {
                    state.ball.Direction.Y -= 0.5f;
                }
                else if (state.ball.Position.Y >= state.redShieldRight.position.Y + 0.25f)
                {
                    state.ball.Direction.Y += 0.5f;
                }

                state.ball.Direction.Normalize();

                SoundManager.PlaySound("BallCatched");
            }
            else if ((currentShieldLeftContainment == ContainmentType.Intersects) && (oldShieldLeftContainment == ContainmentType.Disjoint))
            {
                state.ball.Direction.Z *= -1.0f;

                if (state.ball.Position.X <= state.redShieldLeft.position.X - 0.25f)
                {
                    state.ball.Direction.X -= 0.5f;
                }
                else if (state.ball.Position.X >= state.redShieldLeft.position.X + 0.25f)
                {
                    state.ball.Direction.X += 0.5f;
                }
                if (state.ball.Position.Y <= state.redShieldLeft.position.Y - 0.25f)
                {
                    state.ball.Direction.Y -= 0.5f;
                }
                else if (state.ball.Position.Y >= state.redShieldLeft.position.Y + 0.25f)
                {
                    state.ball.Direction.Y += 0.5f;
                }

                state.ball.Direction.Normalize();

                SoundManager.PlaySound("BallCatched");
            }
            oldShieldRightContainment = currentShieldRightContainment;
            oldShieldLeftContainment = currentShieldLeftContainment;

            // Gestione della collisione con lo scudo dell'avversario
            currentShieldOneContainment = state.blueShield.BoundingBox.Contains(s);
            if ((currentShieldOneContainment == ContainmentType.Intersects) && (oldShieldOneContainment == ContainmentType.Disjoint))
            {
                state.ball.Direction.Z *= -1.0f;

                if (state.ball.Position.X <= state.blueShield.position.X - 0.25f)
                {
                    state.ball.Direction.X -= 0.5f;
                }
                else if (state.ball.Position.X >= state.blueShield.position.X + 0.25f)
                {
                    state.ball.Direction.X += 0.5f;
                }
                if (state.ball.Position.Y <= state.blueShield.position.Y - 0.25f)
                {
                    state.ball.Direction.Y -= 0.5f;
                }
                else if (state.ball.Position.Y >= state.blueShield.position.Y + 0.25f)
                {
                    state.ball.Direction.Y += 0.5f;
                }

                state.ball.Direction.Normalize();

                SoundManager.PlaySound("BallCatched");
            }

            oldShieldOneContainment = currentShieldOneContainment;

            if (newMatch) Reset();

            return matchState;
        }
    }
}
